package br.usp.ime.ingpos.testes.services;

import java.util.Date;
import java.util.Iterator;
import java.util.Set;

import org.junit.Before;
import org.junit.Test;

import br.usp.ime.ingpos.modelo.Bolsa;
import br.usp.ime.ingpos.modelo.Candidato;
import br.usp.ime.ingpos.modelo.Curriculo;
import br.usp.ime.ingpos.modelo.DisciplinaEspecial;
import br.usp.ime.ingpos.modelo.FormacaoAcademica;
import br.usp.ime.ingpos.modelo.IniciacaoCientifica;
import br.usp.ime.ingpos.modelo.PosComp;
import br.usp.ime.ingpos.modelo.TipoDeFormacao;
import br.usp.ime.ingpos.modelo.Usuario;
import br.usp.ime.ingpos.modelo.dao.BolsaDAO;
import br.usp.ime.ingpos.modelo.dao.CandidatoDAO;
import br.usp.ime.ingpos.modelo.dao.CurriculoDAO;
import br.usp.ime.ingpos.modelo.dao.DisciplinaEspecialDAO;
import br.usp.ime.ingpos.modelo.dao.FormacaoAcademicaDAO;
import br.usp.ime.ingpos.modelo.dao.IniciacaoCientificaDAO;
import br.usp.ime.ingpos.modelo.dao.UsuarioDao;
import br.usp.ime.ingpos.services.CurriculoService;
import br.usp.ime.ingpos.testes.BancoDeDadosTestCase;
import br.usp.ime.ingpos.web.controllers.UsuarioSessao;

public class CurriculoServiceTeste
    extends
        BancoDeDadosTestCase
{

    private Usuario usuario;
    private UsuarioSessao usuarioSessao;
    private CurriculoService curriculoService;

    public CurriculoServiceTeste(
        String name )
    {
        super( name );
    }

    @Before
    protected void setUp()
        throws Exception
    {
        super.setUp();

        final UsuarioDao usuarioDao = new UsuarioDao( getSessionCreator() );
        usuario = usuarioDao.procurarPorEmail( RegistroNovoUsuarioServiceTeste.EMAIL );
        usuarioSessao = new UsuarioSessao();
        usuarioSessao.setUsuario( usuario );
        curriculoService = new CurriculoService(
            new BolsaDAO( getSessionCreator() ),
            new CandidatoDAO( getSessionCreator() ),
            new CurriculoDAO( getSessionCreator() ),
            new FormacaoAcademicaDAO( getSessionCreator() ),
            new IniciacaoCientificaDAO( getSessionCreator() ),
            usuarioDao,
            usuarioSessao,
            new DisciplinaEspecialDAO( getSessionCreator() ) );

    };

    @SuppressWarnings( "deprecation" )
    public Bolsa instanciaBolsa()
    {
        Bolsa bolsas = new Bolsa();
        bolsas.setTipoBolsa( "Monitoria" );
        bolsas.setNomeInstituicao( "IME" );
        bolsas.setIngressoData( new Date( 2001 - 1900, 11, 10 ) );
        bolsas.setTerminoData( new Date( 2002 - 1900, 11, 10 ) );
        bolsas.setNomeOrientador( "Alfredo" );
        bolsas.setNomeProjeto( "Ingresso na Pos" );
        return bolsas;
    }

    public PosComp instanciaPosComp()
    {
        PosComp posComp = new PosComp();
        posComp.setNotaLogica( 100 );
        posComp.setNotaMatematica( 100 );
        posComp.setNotaTecnologia( 100 );
        posComp.setAno( "2010" );
        posComp.setRealizouPosComp( true );
        return posComp;
    }

    @SuppressWarnings( "deprecation" )
    public FormacaoAcademica instanciaFormacao()
    {
        FormacaoAcademica formacaoAcademica = new FormacaoAcademica();
        formacaoAcademica.setTipoDeFormacao( TipoDeFormacao.GRADUACAO );
        formacaoAcademica.setInstituicao( "IME" );
        formacaoAcademica.setIngressoData( new Date( 2001 - 1900, 11, 10 ) );
        formacaoAcademica.setNomeOrientador( "Obama" );
        formacaoAcademica.setTerminoData( new Date( 2002 - 1900, 11, 10 ) );
        formacaoAcademica.setTitulo( "Mestre" );
        formacaoAcademica.setTituloDissert( "Pombas e o MAC" );
        return formacaoAcademica;
    }

    public IniciacaoCientifica instanciaIniciacao()
    {
        IniciacaoCientifica iniciacaoCientifica = new IniciacaoCientifica();
        iniciacaoCientifica.setNomeInstituicao( "IF" );
        iniciacaoCientifica.setNomeOrientador( "Homer" );
        iniciacaoCientifica.setTemaProjeto( "Duff e a teoria das cordas" );
        return iniciacaoCientifica;
    }

    public DisciplinaEspecial instanciaDisciplinaEspecial()
    {
        DisciplinaEspecial disciplinaEspecial = new DisciplinaEspecial();
        disciplinaEspecial.setAno( "1999" );
        disciplinaEspecial.setConceito( "R" );
        disciplinaEspecial.setDisciplina( "MAC5711" );
        return disciplinaEspecial;

    }

    @Test
    public void testeSalvaFormacaoAcademica()
    {
        final FormacaoAcademica formacaoAcademica = instanciaFormacao();

        final Curriculo curriculoAnterior = curriculoService.getCurriculoUsuarioAtual();

        int numFormacoesAcademicasAnterior = curriculoAnterior.getFormacoesAcademicas() == null ? 0
            : curriculoAnterior.getFormacoesAcademicas().size();

        curriculoService.adicionaFormacaoAcademica( formacaoAcademica );

        final Curriculo curriculoAtual = curriculoService.getCurriculoUsuarioAtual();
        ++numFormacoesAcademicasAnterior;
        assertTrue( numFormacoesAcademicasAnterior == curriculoAtual.getFormacoesAcademicas().size() );
    }

    @Test
    public void testeProcuraFormacaoAcademicaNulo()
    {
        Usuario usuario = usuarioSessao.getUsuario();
        assertNotNull( usuario );
        assertNotNull( ( (Candidato) usuario ) );
        assertNotNull( ( (Candidato) usuario ).getCurriculo() );
        assertNotNull( ( (Candidato) usuario ).getCurriculo().getFormacoesAcademicas() );
        assertFalse( ( (Candidato) usuario ).getCurriculo().getFormacoesAcademicas().isEmpty() );
    }

    // @Test
    // public void testeRemoveFormacaoAcademica()
    // {
    // final Curriculo curriculoAnterior =
    // curriculoService.getCurriculoUsuarioAtual();
    // final Set<FormacaoAcademica> formacoesAcademicas =
    // curriculoAnterior.getFormacoesAcademicas();
    //
    // int numFormacoesAcademicasAnterior = formacoesAcademicas == null ? 0
    // : formacoesAcademicas.size();
    //
    // if( numFormacoesAcademicasAnterior > 0 ) {
    // final FormacaoAcademica formacaoAcademicaRem =
    // formacoesAcademicas.iterator().next();
    // curriculoService.removerFormacaoAcademica(
    // formacaoAcademicaRem.getFormacaoAcademicaId() );
    //
    // // Verificacao
    // final Curriculo curriculoAtual =
    // curriculoService.getCurriculoUsuarioAtual();
    // --numFormacoesAcademicasAnterior;
    // assertTrue( numFormacoesAcademicasAnterior ==
    // curriculoAtual.getFormacoesAcademicas().size() );
    //
    // }

    // }

    @Test
    public void testeSalvaIniciacaoCientifica()
    {
        IniciacaoCientifica iniciacaoCientifica = instanciaIniciacao();
        assertNotNull( iniciacaoCientifica );
        curriculoService.adicionaIniciacaoCientifica( iniciacaoCientifica );

        Candidato cand = (Candidato) usuarioSessao.getUsuario();
        assertNotNull( cand );
        Curriculo curriculo = cand.getCurriculo();
        assertNotNull( curriculo );
        Set<IniciacaoCientifica> iniciacoes = curriculo.getIniciacoesCientificas();
        assertNotNull( iniciacoes );

        assertTrue( iniciacoes.contains( iniciacaoCientifica ) );
    }

    @Test
    public void testeSalvaPosComp()
    {
        final PosComp posComp = instanciaPosComp();
        final Curriculo curriculo = curriculoService.getCurriculoUsuarioAtual();

        curriculo.setPosComp( posComp );
        curriculoService.atualizarCurriculo( curriculo );

        assertEquals( posComp, ( (Candidato) usuario ).getCurriculo().getPosComp() );
    }

    @Test
    public void testeAtualizarCurriculo()
    {
        final Curriculo curriculo = curriculoService.getCurriculoUsuarioAtual();
        final Long idPrePersist = curriculo.getCurriculoID();
        String expProf = "Experiencia como profissional de programa...";

        curriculo.setExperienciaProfissional( expProf );
        curriculoService.atualizarCurriculo( curriculo );

        Curriculo curriculoPosPersist = curriculoService.getCurriculoUsuarioAtual();

        assertNotNull( curriculoPosPersist );
        assertEquals( idPrePersist, curriculoPosPersist.getCurriculoID() );
        assertEquals( curriculoPosPersist.getExperienciaProfissional(), expProf );
    }
    
    @Test
    public void testeAdicionarDisciplinaEspecial()
    {
        DisciplinaEspecial disciplinaEspecial = instanciaDisciplinaEspecial();
        Curriculo curriculo = curriculoService.getCurriculoUsuarioAtual();
        final int numeroDeDisciplinasAtual = curriculo.getDisciplinasEspeciais().size();
        curriculoService.adicionarDisciplina( disciplinaEspecial );
        assertEquals( numeroDeDisciplinasAtual + 1, curriculo.getDisciplinasEspeciais().size() );
    }

    public DisciplinaEspecial pegarDisciplinaPorID(
        Long id,
        Set<DisciplinaEspecial> disciplinas )
    {
        for( DisciplinaEspecial disciplinaEspecial : disciplinas )
            if( disciplinaEspecial.getDisciplinaEspecialID() == id )
                return disciplinaEspecial;
        return null;
    }

    @Test
    public void testeAtualizarDisciplinaEspecial()
    {
        Curriculo curriculo = curriculoService.getCurriculoUsuarioAtual();
        Set<DisciplinaEspecial> disciplinas = curriculo.getDisciplinasEspeciais();
        assertTrue( disciplinas.size() > 0 );
        DisciplinaEspecial disciplina = disciplinas.iterator().next();

        String novoAno;
        String ano = disciplina.getAno();
        assertNotNull( ano );
        if( ano.equals( "2000" )) {
            novoAno = "2001";
        } else {
            novoAno = "2000";
        }
        disciplina.setAno( novoAno );
        curriculoService.adicionarDisciplina( disciplina );
        
        disciplinas = curriculo.getDisciplinasEspeciais();
        assertTrue( disciplinas.size() > 0 );
        boolean encontrou = false;
        for( DisciplinaEspecial disc : disciplinas) {
            if (disc.equals( disciplina )) {
                assertTrue( disc.getAno().equals( novoAno ) );
                encontrou = true;
            }
        }
        assertTrue( encontrou );
    }

    @Test
    public void testeRemoverDisciplinaEspecial()
    {
        Curriculo curriculo = curriculoService.getCurriculoUsuarioAtual();
        Set<DisciplinaEspecial> disciplinas = curriculo.getDisciplinasEspeciais();
        final int numeroDeDisciplinas = disciplinas.size();
        Iterator<DisciplinaEspecial> iterador = disciplinas.iterator();
        DisciplinaEspecial disciplina = iterador.next();
        curriculoService.removerDisciplinaEspecial( disciplina.getDisciplinaEspecialID() );
        assertEquals( numeroDeDisciplinas - 1, curriculo.getDisciplinasEspeciais().size() );
    }
}